package cn.wolfcode.web.systemlog;

import cn.wolfcode.domain.Employee;
import cn.wolfcode.domain.SystemLog;
import cn.wolfcode.service.ISystemLogService;
import cn.wolfcode.util.RequestUtils;
import cn.wolfcode.util.RequirePermission;
import cn.wolfcode.util.UserContext;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

@Component //把当前类注入到spring容器中
@Aspect    //把当前类标识为一个切面供容器读取
public class AopConfig {

    @Autowired
    private ISystemLogService systemLogService;

    /**
     * 指定切入点
     * 对贴有自定义注解@RequiredPermission的方法，进行切面
     */
    @Pointcut("@annotation(cn.wolfcode.util.RequirePermission)")
    private void useMethod() {}

    /**
     * 对切入点进行增强
     */
    @Around(value = "useMethod()")
    public Object recordLog(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //执行方法前的操作
        //创建日志类对象
        SystemLog systemLog = new SystemLog();

        //给用户名设置
        Employee currentUser = UserContext.getCurrentUser();
        systemLog.setUsername(currentUser.getUsername());

        //获取当前类字节码对象
        Class<?> clz = proceedingJoinPoint.getTarget().getClass();
        //获取方法签名
        MethodSignature signature = (MethodSignature)proceedingJoinPoint.getSignature();

        //类名称
        String clzName = clz.getName();
        String realClzName = clzName.substring(clzName.lastIndexOf(".")).substring(1);
        //获取方法名
        String methodName = signature.getName();
        //设置请求方法
        systemLog.setRequestMethod(realClzName +":"+ methodName);

        //获取方法对象
        Method targetMethod= clz.getDeclaredMethod(methodName, signature.getParameterTypes());
        //获取权限名称
        RequirePermission annotation = targetMethod.getAnnotation(RequirePermission.class);
        //设置执行操作名称
        systemLog.setOperateName(annotation.name());

        //获取请求对象的工具类
        HttpServletRequest request = RequestUtils.getHttpServletRequest();
        //获取ip,工具类
        String ip = RequestUtils.getIp(request);
        systemLog.setUserIp(ip);

        //获取请求参数
        /*Object[] args = proceedingJoinPoint.getArgs();*/
        String requestParam = JSON.toJSONString(request.getParameterMap());
        systemLog.setRequestParameter(requestParam);

        Object result = null;
        //操作前记录时间
        Date date1 = new Date();
        try {
            //执行操作
            result = proceedingJoinPoint.proceed();
            systemLog.setResult("成功");
            systemLog.setErrorMessage("无");
        }catch (RuntimeException e){
            e.printStackTrace();
            systemLog.setResult("失败");
            systemLog.setErrorMessage(e.getMessage());
            throw new RuntimeException(e.getMessage());
        }finally {
            //执行方法后的操作
            Date date2 = new Date();
            //给操作时间设值
            systemLog.setOperateTime(date2);
            long time = date2.getTime() - date1.getTime();
            systemLog.setConductTime(Long.toString(time));
            systemLogService.save(systemLog);
            //result是方法的返回值，直接return回去就会返回给springmvc处理
            return result;
        }
    }
}